import store from "./store";
import {
    ElMessage
} from "element-plus";
import router from "../router";

const API_PATH = "http://localhost:8080"

class BizError extends Error {
    code = -1;

    constructor(message, code = -1) {
        super(message);
        this.code = code;
    }
}

/**
 *
 * @param api
 * @param {'GET'|'POST'|'FILE'|string} method
 * @param postData
 */
function request(api, method = 'GET', postData = {}, progressChange = null) {
    //return fetch(API_PATH + api).then(res => res.json());
    /**
     *
     * @type {RequestInit}
     */
    let options = {
        method
    };
    if (method.toUpperCase() == 'GET') {
        // post => 'key=value&key1=value1'
        const params = [];
        for (let key in postData) {
            params.push(`${key}=${postData[key]}`);
        }
        api += (api.includes('?') ? '&' : '?') + params.join('&');
    } else if (method.toUpperCase() == 'FILE') {
        options = {
            method: 'POST',
            body: postData, // 参数
        }
    } else {
        options = {
            method,
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify(postData) // 参数
        }
    }
    let Authorization = store.getters.userToken
    if (Authorization) {
        if(!options.headers) {
            options.headers = {}
        }
        options.headers.Authorization = Authorization;
        // options = {
        //     ...options,
        //     headers: {
        //         Authorization
        //     }
        // }
    }

    return new Promise((resolve, reject) => {
        /**
         *
         * @param {ApiResult} result
         */
        const processResult = (result, a, b) => {
            if (result.code === 0) { // 判断响应码是否正常
                resolve(result.data)
            } else {
                const route = router.currentRoute.value;
                // 未登录或token无效
                if (result.code == 401) {
                    store.commit('clearToken') // 清除token
                    ElMessage.error('登录凭证验证失败,请重新登录');
                    if (route.path != '/login') router.replace('/login').then(() => console.log('auth show login')).catch();
                    reject(null)
                    return;
                }
                // 其他异常 直接抛出错误
                reject(new BizError(result.message, result.code))
            }
        }
        fetch(API_PATH + api, options)
            .then(res => res.json())
            .then(processResult)
            .catch(e => {
                console.log(e)
                reject(e);
            })
    });
}

export default {
    user: {
        login(params) {
            return request('/api/user/login', 'POST', params);
        },
        signup(params) {
            return request('/api/user/reg', 'POST', params);
        },
        info() {
            return request('/api/user/info');
        },
        checkEmail(email) {
            return request('/api/user/check-email', 'GET', {email});
        },
        checkAccount(account) {
            return request('/api/user/check-account', 'GET', {account});
        }
    },
    folder: {
        /**
         * 列出所有的子文件列表
         * @param path
         * @returns {Promise<Array>}
         */
        list(folderPath = '/') {
            return request(`/api/folder/list`, 'GET', {folderPath})
        },
        create(parent, name) {
            return request(`/api/folder/create`, 'POST', {parent, name});
        }
    },
    file: {
        /**
         * 快速上传
         * @param params
         * @returns {Promise<unknown>}
         */
        fastUpload(params) {
            return request('/api/fast-upload', 'POST', params);
        },
        delete(file) {
            return request('/api/file/delete', 'POST', file);
        },
        rename(file) {
            return request('/api/file/rename', 'POST', file);
        },
        upload(parent, file, onProcess = null) {
            let Authorization = store.getters.userToken
            if(!Authorization){
                ElMessage.error('登录凭证验证失败,请重新登录');
                const route = router.currentRoute.value;
                if (route.path != '/login') router.replace('/login').then(() => console.log('auth show login')).catch();
                return Promise.reject(Error('登录凭证验证失败'));
            }
            // 上传文件到某个目录
            const postData = new FormData(); // 将数据封装成form表单
            postData.append("parent", parent); // 父目录
            postData.append("file", file);// 文件
            return new Promise((resolve, reject) => {
                let request = new XMLHttpRequest();
                request.open('POST', API_PATH + '/api/upload');
                request.setRequestHeader("Authorization",Authorization);
                request.upload.addEventListener('progress', function (e) {
                    // upload progress as percentage
                    let progress = (e.loaded / e.total) * 100;
                    onProcess({
                        uploaded: e.loaded,
                        total: e.total,
                        progress
                    })
                });
                request.addEventListener('load', function (e) {
                    // HTTP status message (200, 404 etc)
                    let ret = {message: null}
                    try {
                        ret = JSON.parse(request.response)
                        if (request.status == 200) {
                            resolve(JSON.parse(request.response));
                        } else {
                            reject(Error(ret.message || '上传文件出错!'));
                        }
                    } catch (e) {
                        console.log(e)
                        reject(Error('上传文件异常'))
                    }
                });
                request.send(postData);
            })
            // return request('/api/upload', 'FILE', postData, onProcess)
        }
    },
    share: {
        /**
         *
         * @param {ShareInfo} info
         */
        create(info) {
            return request('/api/share/create', 'POST', info)
        },
        /**
         *
         * @param {string} id
         * @returns {Promise<ShareData>}
         */
        info(id){
            return request('/api/share/info', 'GET', {id})
        },
        list(id,parent='/',password){
            return request('/api/share/list', 'GET', {id,parent,password})
        }
    },
    code() {
        return request('/create');
    },
    sendCode(email) {
        return request('/send-code','GET',{email});
    }
}